From: Nicholas Wilson Date: Thu, 27 Aug 2026 15:52:16 +0000 (+0100) Subject: Backport of pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch X-Git-Tag: archive/raspbian/10.46-1_deb13u2+rpi1^2~3 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=a67c2ceccc40a098b08026d42f7ff26c4a3c7e22;p=pcre2.git Backport of pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch Cherry-pick of 4889caf31a4c5a6b3c051f0031bf2dbd78f2c287 Fix invalid UTF backwards-scan reads; see GHSA-9qww-pwc4-77qq for details (cherry picked from commit e1fd2e68fe364d14a01ec42bf07201d9820eee8e) --- diff --git a/src/pcre2_extuni.c b/src/pcre2_extuni.c index 91d839e..1bf1c14 100644 --- a/src/pcre2_extuni.c +++ b/src/pcre2_extuni.c @@ -57,12 +57,12 @@ support, because some compilers do not like functionless source files. */ #ifndef SUPPORT_UNICODE PCRE2_SPTR -PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject, +PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR check_subject, PCRE2_SPTR end_subject, BOOL utf, int *xcount) { (void)c; (void)eptr; -(void)start_subject; +(void)check_subject; (void)end_subject; (void)utf; (void)xcount; @@ -83,7 +83,7 @@ same behaviour. Arguments: c the first character eptr pointer to next character - start_subject pointer to start of subject + check_subject pointer to start of validated subject end_subject pointer to end of subject utf TRUE if in UTF mode xcount pointer to count of additional characters, @@ -93,7 +93,7 @@ Returns: pointer after the end of the sequence */ PCRE2_SPTR -PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject, +PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR check_subject, PCRE2_SPTR end_subject, BOOL utf, int *xcount) { BOOL was_ep_ZWJ = FALSE; @@ -124,7 +124,7 @@ while (eptr < end_subject) /* bptr is pointing to the left-hand character */ - while (bptr > start_subject) + while (bptr > check_subject) { bptr--; if (utf) diff --git a/src/pcre2_match.c b/src/pcre2_match.c index faedff7..7d51cf8 100644 --- a/src/pcre2_match.c +++ b/src/pcre2_match.c @@ -2802,7 +2802,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, else { GETCHARINCTEST(fc, Feptr); - Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, utf, + Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject, utf, NULL); } CHECK_PARTIAL(); @@ -3151,7 +3151,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, else { GETCHARINCTEST(fc, Feptr); - Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, + Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject, utf, NULL); } CHECK_PARTIAL(); @@ -3969,7 +3969,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, else { GETCHARINCTEST(fc, Feptr); - Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, + Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject, utf, NULL); } CHECK_PARTIAL(); @@ -4552,7 +4552,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, else { GETCHARINCTEST(fc, Feptr); - Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, + Feptr = PRIV(extuni)(fc, Feptr, mb->check_subject, mb->end_subject, utf, NULL); } CHECK_PARTIAL(); @@ -6123,7 +6123,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, { for (i = 0; i < Lmax; i++) { - if (Feptr == mb->start_subject) + if (Feptr <= mb->check_subject) { if (i < Lmin) RRETURN(MATCH_NOMATCH); Lmax = i; diff --git a/testdata/testinput10 b/testdata/testinput10 index 3309f5e..a7d30b2 100644 --- a/testdata/testinput10 +++ b/testdata/testinput10 @@ -573,6 +573,16 @@ AAA\x80BXYZ AAA\x80BBXYZ +# Backward scans must not enter the invalid prefix before check_subject. + +/(?<=a{1,2})X/utf,match_invalid_utf +\= Expect no match + \x80X + +/\X\X/utf,match_invalid_utf +\= Expect no match + \x80\x{1f1e6}\x{1f1e7} + # ------------------------------------- /(*UTF)(?=\x{123})/I diff --git a/testdata/testinput12 b/testdata/testinput12 index 9763f73..b789b00 100644 --- a/testdata/testinput12 +++ b/testdata/testinput12 @@ -486,6 +486,16 @@ /(..)(*scs:(1)ab$)/match_invalid_utf ab\x{df00}cde +# Backward scans must not enter the invalid prefix before check_subject. + +/(?<=a{1,2})X/utf,match_invalid_utf +\= Expect no match + \x{dc00}X + +/\X\X/utf,match_invalid_utf +\= Expect no match + \x{dc00}\x{1f1e6}\x{1f1e7} + # ---------------------------------------------------- /(*UTF)(?=\x{123})/I diff --git a/testdata/testoutput10 b/testdata/testoutput10 index d1bccf3..9b5b670 100644 --- a/testdata/testoutput10 +++ b/testdata/testoutput10 @@ -1745,6 +1745,18 @@ No match AAA\x80BBXYZ No match +# Backward scans must not enter the invalid prefix before check_subject. + +/(?<=a{1,2})X/utf,match_invalid_utf +\= Expect no match + \x80X +No match + +/\X\X/utf,match_invalid_utf +\= Expect no match + \x80\x{1f1e6}\x{1f1e7} +No match + # ------------------------------------- /(*UTF)(?=\x{123})/I diff --git a/testdata/testoutput12-16 b/testdata/testoutput12-16 index bd4d524..64a7dd8 100644 --- a/testdata/testoutput12-16 +++ b/testdata/testoutput12-16 @@ -1626,6 +1626,18 @@ No match 0: ab 1: ab +# Backward scans must not enter the invalid prefix before check_subject. + +/(?<=a{1,2})X/utf,match_invalid_utf +\= Expect no match + \x{dc00}X +No match + +/\X\X/utf,match_invalid_utf +\= Expect no match + \x{dc00}\x{1f1e6}\x{1f1e7} +No match + # ---------------------------------------------------- /(*UTF)(?=\x{123})/I diff --git a/testdata/testoutput12-32 b/testdata/testoutput12-32 index c9587ee..00133e2 100644 --- a/testdata/testoutput12-32 +++ b/testdata/testoutput12-32 @@ -1624,6 +1624,18 @@ No match 0: ab 1: ab +# Backward scans must not enter the invalid prefix before check_subject. + +/(?<=a{1,2})X/utf,match_invalid_utf +\= Expect no match + \x{dc00}X +No match + +/\X\X/utf,match_invalid_utf +\= Expect no match + \x{dc00}\x{1f1e6}\x{1f1e7} +No match + # ---------------------------------------------------- /(*UTF)(?=\x{123})/I